#include <time.h>
#include <cstdarg>
#include <string.h>
#include <streambuf>
#include <pthread.h>
#include "Logger.h"
#include "Util.h"

#define DEFAULT_PATH "Logs.txt"

char noCharacter[9] = {'<', '>', ':', '/', '|', '"', '?', '*', '\\'};

bool isDiferent(const char* value)
{
    bool acecpted = true;
    int index = 0;
    while (value != 0 && index < 9 && (acecpted = *value != noCharacter[index++]));
    return acecpted;
}

//It should not acept characters : < > : / | " ? \ * 
//TODO no key words : CON, PRN, AUX, CLOCK$, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8 y LPT9

bool validateFileName(const char* word)
{
    bool result = true;
    while (*word != '\0' && (result = isDiferent(word++)));
    return result;
}
// Here w+ means that a directory creates if does not exist , and overwrite if exist

void Logger::createFile(const char* name)
{
    if (validateFileName(name))
        Logger::logFile_ = fopen(name, "w+");
    else
    {
        Logger::logFile_ = fopen(DEFAULT_PATH, "w+");
        Logger::log(WARNING, "%s", "File was created with default name Logs.txt because the name contains special caracters");
    }
}

Logger logger;

Logger::Logger()
{
    levelControl_ = DEBUG;
    createFile(DEFAULT_PATH);
}

Logger::Logger(LogType levelControl) : levelControl_(levelControl)
{
    createFile(DEFAULT_PATH);
}

Logger::Logger(LogType levelControl, const char* name) : levelControl_(levelControl)
{
    createFile(name);
}

Logger::~Logger()
{
    fclose(logFile_);
    logFile_ = 0;
}

void Logger::setLevelControl(LogType type)
{
    this->levelControl_ = type;
}

void Logger::getDate(const char* format, char* buffer, unsigned int size)
{
    time_t rawtime;
    struct tm * timeinfo;

    time(&rawtime);
    timeinfo = localtime(&rawtime);

    strftime(buffer, size, format, timeinfo);
}

void Logger::buildLog()
{

}

void Logger::log(LogType type, const char* nameFuntion, const char* format, ...)
{
    if (type <= levelControl_)
    {
        char log[100];
        const char* logType = parseToChars(type);
        char args[100];
        va_list varList;
        va_start(varList, format);
        vsprintf(args, format, varList);
        va_end(varList);
        char date[50];
        getDate("%b-%d-%y %H:%M:%S", date, 50);
        Util::format(log, "%s: %s Function[%s] Thread[%d] %s\n", logType, args,
                     nameFuntion, pthread_self(), date);
        printf("%s", log);
        fprintf(logFile_, "%s", log);

    }
}

const char* Logger::parseToChars(LogType type)
{
    switch (type)
    {
    case DEBUG:
        return "DEBUG";
    case INFO:
        return "INFO";
    case WARNING:
        return "WARN";
    }
}

